package com.example.concurrency.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author ZhenWuWang
 */
public class ThreadPoolDemo
{
    private ExecutorService threadPool = new MyThreadPoolExecutor(5, 10, 1,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(5),
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args)
    {
        ThreadPoolDemo threadPoolDemo = new ThreadPoolDemo();
//        threadPoolDemo.testCorePoolSize();
//        threadPoolDemo.testBlockingDeque();
//        threadPoolDemo.testMaximumPoolSize();
        threadPoolDemo.testAbortPolicy();
    }

    public void testCorePoolSize()
    {
        for (int i = 0; i < 5; i++)
        {
            threadPool.execute(new MyRunnableImpl("线程" + i));
        }
    }

    /**
     * 当线程数大于corePoolSize时候，多出的任务会被仍进阻塞队列，而不是立刻创建临时线程（maximumPoolSize）
     * 首先被执行的任务完成后，队列的任务才会被执行
     */
    public void testBlockingDeque()
    {
        for (int i = 0; i < 10; i++)
        {
            threadPool.execute(new MyRunnableImpl("线程" + i));
        }
    }

    /**
     * 当阻塞队列也满的时候，会创建临时线程去执行任务
     */
    public void testMaximumPoolSize()
    {
        for (int i = 0; i < 15; i++)
        {
            threadPool.execute(new MyRunnableImpl("线程" + i));
        }
    }

    /**
     * 当任务数大于MaximumPoolSize时候，会执行拒绝策略
     * 这里AbortPolicy会舍弃任务并且抛出异常
     */
    public void testAbortPolicy()
    {
        for (int i = 0; i < 16; i++)
        {
            threadPool.execute(new MyRunnableImpl("线程" + i));
        }
    }

    private static class MyRunnableImpl implements Runnable, MyRunnable
    {
        private final String name;

        private MyRunnableImpl(String name)
        {
            this.name = name;
        }

        @Override
        public void run()
        {
            for (int i = 0; i < 5; i++)
            {
                System.out.println("name:" + name + " ==》 " + i);
                try
                {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public String getName()
        {
            return name;
        }
    }
}
